#include "eventbase.hpp"
#include "eventhandler.hpp"
#include "logger.hpp"
#include <event2/bufferevent.h>
#include <event2/event-config.h>

namespace oraysock5 {
EventBase::EventBase()
{
    const EventConfig cfg;
    if (cfg.setfeatures(EV_FEATURE_ET) == -1) {
        THROW_EXCEPTION("call setfeatures(EV_FEATURE_ET)");
    }
    if (cfg.setfeatures(EV_FEATURE_O1) == -1) {
        THROW_EXCEPTION("call setfeatures(EV_FEATURE_O1)");
    }
    if (cfg.setflag(EVENT_BASE_FLAG_IGNORE_ENV) == -1) {
        THROW_EXCEPTION("call setfeatures(EVENT_BASE_FLAG_IGNORE_ENV)");
    }
    if (cfg.setflag(EVENT_BASE_FLAG_EPOLL_USE_CHANGELIST) == -1) {
        THROW_EXCEPTION("call setflag(EVENT_BASE_FLAG_EPOLL_USE_CHANGELIST)");
    }
    base_ = event_base_new_with_config(cfg.config());
    if (base_ == nullptr) {
        THROW_EXCEPTION("call event_base_new_with_config");
    }
}
EventBase::EventBase(const EventConfig* cfg)
{
    base_ = event_base_new_with_config(cfg->config());
    if (base_ == nullptr) {
        THROW_EXCEPTION("call event_base_new_with_config");
    }
}
EventBase::~EventBase()
{
    if (base_ != nullptr)
        event_base_free(base_);
}
event_base* EventBase::base() const
{
    return base_;
}
int EventBase::dispatch() const
{
    return event_base_dispatch(base_);
}
int EventBase::loop(int flag) const
{
    event_base_loop(base_, flag);
    return 0;
}
int EventBase::loopexit(const timeval* tv) const
{
    return event_base_loopexit(base_, tv);
}
int EventBase::loopbreak() const
{
    return event_base_loopbreak(base_);
}
bool EventBase::gotexit() const
{
    return event_base_got_exit(base_);
}
bool EventBase::gotbreak() const
{
    return event_base_got_break(base_);
}
int EventBase::addevent(const std::shared_ptr<EventHandler> handler, const timeval* tv) const
{
    return addevent(handler.get(), tv);
}
int EventBase::addevent(const EventHandler* handler, const timeval* tv) const
{
    return event_add(handler->event(), tv);
}
int EventBase::delevent(const std::shared_ptr<EventHandler> handler) const
{
    return delevent(handler.get());
}
int EventBase::delevent(const EventHandler* handler) const
{
    return event_del(handler->event());
}
void EventBase::event_shutdown()
{
    libevent_global_shutdown();
}
}
